package com.engr.lyx.blog.biz.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.engr.lyx.blog.biz.enums.StatusEnum;
import com.engr.lyx.blog.biz.enums.TypeEnums;
import com.engr.lyx.blog.biz.repository.article.ArticleRepository;
import com.engr.lyx.blog.biz.repository.article.ArticleVisitLogRepository;
import com.engr.lyx.blog.biz.service.ArticleService;
import com.engr.lyx.blog.client.dto.ArticleDTO;
import com.engr.lyx.blog.client.entity.Article;
import com.engr.lyx.blog.client.vo.ArchiveVO;
import com.engr.lyx.blog.client.vo.ArticleArchiveVO;
import com.engr.lyx.blog.client.vo.ArticleVO;
import com.engr.lyx.common.exception.ServiceException;
import com.engr.lyx.common.utils.BeanUtils;
import com.engr.lyx.common.utils.PageUtil;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @program: blog
 * @desc:
 * @author: lyx
 * @date: 2019-05-09 20:17
 **/
@Service
public class ArticleServiceImpl implements ArticleService {

    @Autowired
    private ArticleRepository articleRepository;

    @Autowired
    private ArticleVisitLogRepository articleVisitLogRepository;

    @Override
    public Article selectById(ArticleDTO articleDto) {

        if (TypeEnums.ABOUT.getType() == articleDto.getType()) {
            return articleRepository.findById((long) TypeEnums.ABOUT.getType())
                    .orElseThrow(() -> new ServiceException("couldn't found user info"));
        }
        Optional<Article> opt = articleRepository.findById(NumberUtils.toLong(articleDto.getId()));
        return opt.get();
    }

    @Override
    public Object selectByUserId(Long userId, Pageable pageable) {

        Page<Article> page = articleRepository.findByUserId(userId, pageable);

        return PageUtil.toPage(page);
    }

    @Override
    public List<ArticleVO> selectTopArticleVisit(Long userId) {

        List<Map<String, Object>> articleTopVos = articleVisitLogRepository.findTopArticle(userId);
        if (articleTopVos != null && articleTopVos.size() > 0) {
            List<ArticleVO> data = articleTopVos.stream().map(x -> {
                ArticleVO articleVo = new ArticleVO();
                articleVo = BeanUtils.mapToObject(x, ArticleVO.class);
                return articleVo;
            }).collect(Collectors.toList());
            return data;
        }
        return Collections.emptyList();
    }

    @Override
    public Page<Article> selectArticlesByTagId(Integer tagId, Long userId, Pageable pageable) {

        return articleRepository.findByTagIdAndUserId(tagId, userId, pageable);
    }

    @Override
    public List<Article> selectAllByOrderByTags2Desc(Long userId) {

        return articleRepository.findAllByOrderByTags2Desc(userId);
    }

    @Override
    public List<Article> selectArticleByIdNear(long id, long userId) {

        List<Article> list = Lists.newLinkedList();
        Optional<Article> pre = articleRepository.findPreArticle(id, userId);
        pre.ifPresent(x -> list.add(x));
        Optional<Article> next = articleRepository.findNextArticle(id, userId);
        next.ifPresent(x -> list.add(x));
        return list;
    }

    @Override
    public List<ArticleArchiveVO> selectByArchive() {

        List<ArticleArchiveVO> list = Lists.newArrayList();
        List<Article> articles = articleRepository.findByStatusOrderByPublishDateDesc(StatusEnum.EFFECTIVE.getCode());
        if (CollUtil.isNotEmpty(articles)) {
            Map<String, List<Article>> map = articles.stream().collect(Collectors.groupingBy(e -> DateFormatUtils.format(e.getPublishDate(), "yyyy")));
            if (CollUtil.isNotEmpty(map)) {
                map.forEach((k, v) -> {
                    ArticleArchiveVO articleArchiveVO = new ArticleArchiveVO();
                    articleArchiveVO.setYear(k);
                    List<ArchiveVO> archiveVOS = BeanUtils.coverToList(v, ArchiveVO.class);
                    articleArchiveVO.setList(archiveVOS);
                    list.add(articleArchiveVO);
                });
            }
        }

        return list;
    }

}
